package com.lianqi.emcpframework.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * @program emcp-framework
 * @ClassName ClassUtils
 * @description: class操作工具类
 * @author: sky
 * @create: 2018/11/13 16:50
 */
public class ClassUtils {
    /**
     * 获取类的注解如果没有则从父类获取
     * @param clazz 类的class属性
     * @param annotation 注解class
     * @param <T>  注解类型泛型
     * @return  注解
     */
    public static <T extends Annotation> T getAnnotation(Class<?> clazz,Class<T> annotation){
         T ann = clazz.getAnnotation(annotation);
         if (ann != null){
             return ann;
         }
         else if (clazz.getSuperclass() != Object.class){
             return getAnnotation(clazz.getSuperclass(),annotation);
         }
         return ann;
    }

    /**
     * 获取方法的注解如果没有则从父类方法获取
     * @param method 方法
     * @param annotation 注解class
     * @param <T> 注解类型泛型
     * @return  注解
     */
    public static <T extends Annotation> T getAnnotation(Method method, Class<T> annotation){
        T ann = method.getAnnotation(annotation);
        if (ann != null){
            return ann;
        }else {
            try {
                Class clazz = method.getDeclaringClass();
                Class superClass = clazz.getSuperclass();
                if (superClass != Object.class){
                    Method superMethod = null;
                    superMethod = superClass.getMethod(method.getName(),method.getParameterTypes());
                    return getAnnotation(superMethod,annotation);
                }
                } catch (NoSuchMethodException e) {
                   return null;
                }
        }
        return ann;
    }

    /**
     * 根据参数化类型获取泛型
     * @param genType 参数化类型
     * @param index  索引
     * @return  泛型
     */
    private static Class<?> getGenericTypeByParameterizedType(ParameterizedType genType,int index){
        Type[] params = genType.getActualTypeArguments();
        if (index >= params.length || index < 0){
            return null;
        }
        Object param = params[index];
        if (param instanceof  Class){
            return ((Class) param);
        }
        //如果是集合类型
        if (param instanceof  ParameterizedType){
            return (Class<?>) ((ParameterizedType)param).getRawType();
        }
        return null;
    }

    /**
     * 获取一个类的泛型类型，如果未获取到返回 Object.class
     * @param clazz 要获取的类
     * @param index 索引
     * @return 泛型
     */
    public static Class<?> getGenericType(Class clazz,int index){
        List<Type> types = new ArrayList<>();
        types.add(clazz.getGenericSuperclass());
        types.addAll(Arrays.asList(clazz.getGenericInterfaces()));
        return types.stream().filter(Objects::nonNull)
                .map(type -> {
                    if (clazz != Object.class && !(type instanceof ParameterizedType)){
                        return getGenericType(clazz.getSuperclass(),index);
                    }
                    return getGenericTypeByParameterizedType((ParameterizedType)type,index);
                })
                .filter(Objects::nonNull)
                .filter(res -> res != Object.class)
                .findFirst()
                .orElse((Class)Object.class);
    }

    /**
     * 获取一个类的第一个泛型类型
     * @param clazz 要获取的类
     * @return 泛型
     */
    public static Class<?> getGenericType(Class clazz){
        return  getGenericType(clazz,0);
    }


    public static boolean instanceOf(Class clazz,Class target){
        if (clazz == null) {
            return false;
        }
        if (clazz == target) {
            return true;
        }

        if (target.isInterface()){
            for (Class aClass : clazz.getInterfaces()){
                if (aClass == target){
                    return true;
                }

            }
        }
        if (clazz.getSuperclass() == target){
            return true;
        }else {
            if (clazz.isInterface()){
                for (Class aClass : clazz.getInterfaces()){
                    if (instanceOf(aClass,target)){
                        return true;
                    }

                }
            }
            return instanceOf(clazz.getSuperclass(),target);
        }
    }

    /**
     * 类型转换
     * @param value 要转换的对象
     * @param type 转换的类型
     * @param <T> 泛型
     * @return 转换后的值
     */
    public static final <T> T cast(Object value,Class<T> type){
        if (value == null) {
            return null;
        }
        Object newVal = null;
        if (instanceOf(value.getClass(),type)){
            newVal = value;
        }else if (type == Integer.class || type == int.class){
            newVal = StringUtils.toInt(type);
        }else if (type == Long.class || type == long.class || type == Float.class || type == float.class){
            newVal = StringUtils.toLong(type);
        }else if (type == Boolean.class || type == boolean.class){
            newVal  = StringUtils.isTrue(type);
        }else if (type == Date.class){
            newVal = DateTimeUtils.formatUnknownString2Date(value.toString());
        }else if (type == String.class){
            if (value instanceof Date){
                newVal = DateTimeUtils.format((Date)value,DateTimeUtils.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
            }else {
                newVal = String.valueOf(value);
            }
        }
        return (T) newVal;
    }

}
